#
# Library.py
# (c) 2008 Will Baker.
#

import os
import re

from ComicLoader import ComicLoader
from Comic import Comic
from Search import Search
from SearchResult import SearchResult
from Tag import Tag

class Library:
    """
    A collection of Comics.
    """
    def __init__( self, root ):
        self.root = root
        self.comics = {}
        self.tags = {}
        self.refresh()
        
    def refresh( self ):
        """
        Traverse the library directory structure, beginning from the root, loading recognised
        Comic file formats.
        """
        # Create a list of the recognised file formats from the plugins.
        recognised_formats = []
        for p in ComicLoader.plugins:
            recognised_formats.extend( p.extensions )
            
        for (root, directories, files) in os.walk( self.root ):
            tokens = re.findall( "[a-z0-9]+", os.path.basename(root).lower() )
            tag = tokens[0]
            for t in range(1, len(tokens)):
                if not tokens[t] in tokens[:t-1]:
                    tag += ' ' + tokens[t]
        
            tag_order = 0
            for f in files:
                path = os.path.join( root, f )
                (name, ext) = os.path.splitext( path )
                
                if ext.lower() in recognised_formats:
                    comic = Comic(path)
                    self.add_comic( comic )
                    self.apply_tag( tag, comic, tag_order )
                    tag_order += 1
        
    def add_comic( self, comic ):
        """
        Add a Comic to this Library.
        """
        self.comics[comic.path] = comic
        
    def apply_tag( self, text, comic, order=-1 ):
        """
        Apply a Tag to a Comic.
        """
        if not text in self.tags:
            self.tags[text] = []
        if not text in comic.tags:
            self.tags[text].append( comic )
            comic.tags[text] = Tag( text, order )
        else:
            comic.tags[text].order = order
         
    def find_comics( self, search_string ):
        """
        Find SearchResults for Comics using search string. The results are sorted by relevance
        before being returned.
        """
        search = Search( search_string )
        return search.apply( self )
        
    def find_comic_by_path( self, path ):
        """
        Find a comic by path.
        """
        if path in self.comics:
            return self.comics[path]
        else:
            return None
            
    def find_adjacent_comic( self, comic, distance ):
        """
        Find an adjacent comic based on tag order.
        """
        tag = comic.tags.values()[ 0 ]
        order = tag.order + distance
        
        for c in self.tags[tag.text]:
            if order == c.tags[tag.text].order:
                return c
                
        return None
